遺留系統是指具有 「系統架構不清晰」、「難以維護及修改」、「缺乏測試流程」、「難以遷移及部署」 等性質的系統。這類系統或許仍然運作,累積了長期使用形成的規則。但卻因為團隊缺乏規範與管理,使得系統在長時間的維護修改下,整體架構變得複雜、高度耦合,進而導致難以維護。為了讓系統能夠繼續使用,則需要 「全面重構」 遺留系統。
遺留系統往往不是由單一問題造成,而是由許多小問題日積月累造成的結果。其中常見的特徵包括:
多個功能可能需要執行相同的處理流程,但各自保留獨立的實作。當這項共同邏輯需要調整時,必須同步修改所有實作。如果遺漏其中一處,可能會造成不同功能產生不一致的結果。
例子
描述:某個系統提供數十個 API,每個 API 都各自實作相同的存取憑證驗證流程。
變更:驗證流程新增憑證期限檢查。
結果:部分介面遺漏修改,仍接受已失效的憑證。
程式中的不同處理邏輯如果直接依賴相同資料的結構、格式或欄位意義,就會出現 「資料高度耦合」 的情況。當資料的結構或表示方式改變時,所有相關處理邏輯都必須同步調整。這會擴大變更範圍,也容易遺漏修改。
例子
描述:某個資料查詢 API 會將資料表中所有欄位以陣列格式回傳,目前程式透過索引值讀取指定欄位的值。
變更:資料表在原有欄位之間加入新的欄位,使 API 回傳陣列中後續欄位的索引值改變。
結果:未同步修改的程式仍從原有索引位置讀取資料,因而取得錯誤欄位的值。
測試、建置與部署流程如果沒有明確且可重複執行的步驟,每次變更難以使用相同方式確認結果。執行方式依賴人工記憶或個別環境時,容易遺漏必要步驟,也無法確認每次產生的成品是否一致。
例子
描述:團隊以人工步驟測試與建置系統程式,再將產生的檔案部署到執行環境。
變更:系統程式新增一個相依函式庫,部署時需要同時複製對應檔案。
結果:部分人員仍沿用舊步驟,部署的系統程式缺少必要檔案而無法啟動。
系統知識如果沒有透過可靠文件記錄,可能只存在少數人員的記憶中。當文件缺失、過時或與實際行為不一致時,其他人員就需要重新探索系統或反覆詢問熟悉系統的人員,增加理解與修改程式所需的時間。
例子
描述:系統部署時需要將特定目錄掛載至指定路徑,但這項設定沒有記錄在文件中,只有原開發人員知道。
變更:原開發人員離開團隊,其他人員需要將系統部署到其他機器上。
結果:接手人員未掛載該目錄,系統無法取得執行所需的檔案,因此無法啟動。
系統長期未更新時,可能依賴已停止支援的程式語言版本、函式庫、作業系統。當這些相依項目無法繼續取得修正或替代時,系統可能無法在新的執行環境中運作,也會增加維護與復原的難度。
例子
描述:系統程式依賴已停止支援的程式語言版本與函式庫。
變更:團隊將建置環境更新至仍受支援的程式語言版本,並替換停止維護的函式庫。
結果:原有程式因語法與函式庫介面不相容而無法完成建置,必須調整程式後才能部署。
重構(Refactor)是改善軟體內部結構,同時維持既有外部行為的工程活動。重構的重點在於處理系統長期累積的技術債,改善系統的可維護性,並降低理解、修改、測試與部署系統的成本。
遺留系統的程式結構如果缺乏清楚的責任範圍,一項功能變更可能同時影響多個處理流程。重構可以重新安排程式責任與相依關係,讓變更集中在明確範圍,降低遺漏修改或影響其他功能的機率。
例子
描述:某個系統的數十個 API 各自實作相同的存取憑證驗證流程。新增憑證期限檢查時,部分 API 曾因遺漏修改而仍接受已失效的憑證。
變更:重構將存取憑證驗證集中為共用流程,並由所有 API 統一呼叫。
結果:後續調整驗證規則時只需要修改共用流程,所有 API 都會套用相同規則,降低遺漏修改的風險。
程式碼結構混亂時,開發人員需要花費額外時間尋找功能的實作位置與相依關係。重構可以改善命名、拆分過長的處理流程並移除重複程式,讓開發人員更容易理解及修改程式。
例子
描述:系統使用一個功能複雜、牽涉多個流程的函式。
變更:重構將不同處理拆分為名稱與責任明確的函式。
結果:開發人員可以直接找到需要修改的函式,不必反覆閱讀整段程式。
遺留系統可能包含特殊規則、架構或操作方法,但只有少數人員掌握其目的與執行方式。重構後可以透過清楚的程式結構、測試與文件記錄這些知識,讓其他開發人員也能理解及維護系統,降低系統對特定人員的依賴。
例子
描述:系統部署時需要將特定目錄掛載至指定路徑,但這項設定沒有記錄在文件中,只有原開發人員知道。
變更:重構時將目錄用途、掛載路徑與操作步驟記錄在部署文件中,並加入啟動檢查確認目錄是否正確掛載。
結果:其他人員可以依照文件完成設定,系統也能在目錄未掛載時提供明確的錯誤訊息,不再需要依賴原開發人員完成部署。
程式如果直接包含特定執行環境的設定,測試與部署前可能需要人工修改程式。重構可以將執行設定與程式邏輯分開,使相同的系統程式能在不同環境中接受測試與部署。
例子
描述:系統程式將資料路徑直接寫在程式碼中,測試與部署前都需要人工修改路徑。
變更:重構將資料路徑改為由執行設定提供,測試與部署使用各自的設定。
結果:團隊可以使用相同的系統程式執行測試與部署,避免人工修改程式造成差異。
技術債會使原本單純的功能變更需要額外處理重複程式、不清楚的相依關係或例外流程。重構可以改善這些設計與實作問題,避免團隊在後續修改中持續付出相同成本。
例子
描述:系統中的多個功能直接使用已停止維護的函式庫,而且各自採用不同的呼叫方式。
變更:重構建立共用流程集中使用該函式庫,並將相依項目替換為仍受支援的版本。
結果:後續更新相依項目時只需要調整共用流程,減少重複修改各項功能的成本。
不是所有遺留系統都值得重構。判斷是否需要重構時,應同時考慮系統的 「使用價值」、「變更頻率」、「維護成本」、「風險與替代方案」。以下情況可以考慮不重構:
但不重構不代表可以不處理系統當前面對的問題。應該先建立最低限度的文件、備份、監控與操作手冊,並記錄未來需要處理的風險。如果系統仍持續提供重要功能,應該定期重新評估重構系統的可行性。
本系列所稱的「全面重構」,是根據既有系統行為重新設計並建置目標系統,同時調整架構、資料模型與功能。後續將從需求與範圍開始,依序討論如何分析既有系統、保護與遷移資料、建置目標系統、執行整體測試、規劃正式切換,以及透過監控與文件降低系統啟用後的風險。